package model;

import static util.Constants.DICTIONARY_ENABLED;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.TreeSet;

import util.Resources;

/**
 * La classe dictionnaire qui s'occupe de la liste des mots autorisés.
 * 
 * Cette classe utilise le pattern Singleton : il n'y a qu'un seul dictionnaire
 * pour toute l'application.
 * 
 * @author Lucile Gramusset et Guillaume Poussel
 */
public class Dictionary {

    /**
     * L'instance unique du dictionnaire.
     */
    private static Dictionary dictionaryInstance;

    /**
     * Retourne l'instance unique du dictionnaire
     * 
     * @return L'instance unique du dictionnaire
     */
    public static Dictionary getInstance() {
        if (dictionaryInstance == null) {
            dictionaryInstance = new Dictionary();
        }
        return dictionaryInstance;
    }

    /**
     * L'ensemble des mots contenus dans le dictionnaire. L'implémentation
     * utilisée est un {@link TreeSet} pour assurer une recherche en {@code
     * log(n)}.
     */
    private Set<String> words;

    /**
     * Construit une instance de dictionnaire et va chercher la liste des mots
     * dans le fichier texte. Ce fichier doit être formé d'un mot par ligne.
     */
    private Dictionary() {
        words = new TreeSet<String>();

        BufferedReader dictionaryText;
        String line = "";
        // Ouvre le dictionnaire
        try {
            
            dictionaryText = new BufferedReader(new InputStreamReader(Resources.getDictionaryInputStream()));
            if (dictionaryText == null) {
                throw new FileNotFoundException(Resources.getString("Dictionary.FileNotFound"));
            }
            // Fill the dictionary ArrayList

            while ((line = dictionaryText.readLine()) != null) {
                add(line);
            }
            dictionaryText.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * Ajoute un mot au dictionnaire. Cette méthode ne touche pas au fichier
     * texte.
     * 
     * @param elem
     *            L'objet dont la représentation en chaîne de caractères sera
     *            ajouté en majuscules au dictionnaire.
     */
    public void add(Object elem) {
        words.add(elem.toString().toUpperCase());
    }

    /**
     * Verifie si un mot est dans le dictionnaire.
     * 
     * Cette méthode utilise également la constante
     * {@link util.Constants#DICTIONARY_ENABLED} pour savoir si elle doit
     * réellement chercher. Cette constante est uniquement là pour les tests.
     * 
     * @param elem
     *            Le mot que l'on recherche
     * 
     * @return <code>true</code> si le dictionnaire contient le mot,
     *         <code>false</code> sinon.
     */
    public boolean contains(Object elem) {
        return !DICTIONARY_ENABLED
                || words.contains(elem.toString().toUpperCase());
    }
}